package com.emeraldparser.grammar;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableSet;

public class Grammar {

	private final ImmutableCollection<? extends Rule> tokenRules;
	private final ImmutableCollection<? extends Rule> productionRules;
	private final ImmutableCollection<? extends Rule> rules;
	private final Rule startRule;

	public Grammar(ImmutableCollection<? extends Rule> tokenRules, ImmutableCollection<? extends Rule> productionRules, Rule startRule) {
		this.tokenRules = tokenRules;
		this.productionRules = productionRules;
		this.rules = ImmutableSet.<Rule>builder().addAll(tokenRules).addAll(productionRules).build();
		this.startRule = startRule;
	}

	public static class Builder {
		
		private final ImmutableSet.Builder<Rule> tokenRules = ImmutableSet.builder();
		private final ImmutableSet.Builder<Rule> productionRules = ImmutableSet.builder();
		private Rule startRule;
		
		public Builder addAll(Grammar prototype) {
			tokenRules.addAll(prototype.getTokenRules());
			productionRules.addAll(prototype.getProductionRules());
			this.startRule = prototype.getStartRule();
			return this;
		}
		
		public Builder addTokenRule(Rule tokenRule) {
			tokenRules.add(tokenRule);
			return this;
		}
		
		public Builder addProductionRule(Rule productionRule) {
			productionRules.add(productionRule);
			return this;
		}
		
		public Builder setStartRule(Rule startRule) {
			this.startRule = startRule;
			return this;
		}
		
		public Grammar build() {
			return new Grammar(tokenRules.build(), productionRules.build(), startRule);
		}
		
	}

	public static Builder builder() {
		return new Builder();
	}

	public ImmutableCollection<? extends Rule> getTokenRules() {
		return tokenRules;
	}

	public ImmutableCollection<? extends Rule> getProductionRules() {
		return productionRules;
	}

	public ImmutableCollection<? extends Rule> getRules() {
		return rules;
	}

	public Rule getStartRule() {
		return startRule;
	}

}
